package datatableaux.rules;

import java.util.HashSet;

import datatableaux.*;
import entities.*;
import entities.concept.*;
import entities.role.Role;

public class DataAllRule {

	private UniversalConcept nextExp;
	private DataCompletion dc;
	private DataBranching br;
	
	
	public DataAllRule(DataCompletion dc) {
		super();
		this.dc = dc;
		this.br = this.dc.getCurrentBranching();
	}
	
	public boolean isApplicable(Individual n){
		HashSet<Concept> unexp = new HashSet<Concept> ();
		unexp.addAll(n.getLabels());
		unexp.removeAll(n.getExpandedLabels());
		if(unexp.size()<1){
			return false;
		}
		for(Concept c : unexp){
			if(c instanceof UniversalConcept){
				UniversalConcept uc = (UniversalConcept) c;
				Role r = uc.getRole();
				if( n.getSuccessors(r) == null){
					continue;
				}
				Concept filler = uc.getFiller(); 
				if( n.getSuccessors(r).size()>0){
					//at least one successor that do not have the filler
					for(Individual nn : n.getSuccessors(r)){
							if(!nn.getLabels().contains(filler)){
								this.nextExp = uc;
								return true;
								}
					}
				}
			}
		}
		return false;
	}
	
	/*
	 * ensure all r-successors will have the filler in its label
	 */
	public boolean applyRule(Individual n){
		boolean suc = false;
		Role r = this.nextExp.getRole();
		Concept filler = this.nextExp.getFiller();
		if(n.getSuccessors(r) == null){
			//vacuously true
			return false;
		}
		boolean all = true;
		for(Individual nn:n.getSuccessors(r)){
			if(!nn.getLabels().contains(filler)){
				nn.addLabels(filler);
				//this successor has been changed, must be added to the queue for expansion
				//already in the queue, no op.
				if(!this.dc.getIndQueue().contains(nn)){
					this.dc.addToQueue(nn, DataCompletion.INQUEUEFIRST);
					if(DataBranchChanges.getRecordingStatus()){
						//this node is added for this branch only, must be recorded
						br.getBranchChanges().addPotentialQueueInds(nn);
					}
				}
				if(DataBranchChanges.getRecordingStatus()){
					br.getBranchChanges().addToLabel(nn, filler);
				}
			}
		}
		suc |= all;

		n.addExpandedLabels(this.nextExp);
		if(DataBranchChanges.getRecordingStatus()){
			br.getBranchChanges().addToExpandedLabel(n, this.nextExp);
		}
		return suc;
	}
	
}
